import 'dart:convert';
import 'dart:io';
import 'package:eshi/app/settings/update/VersionConfig.dart';
import 'package:eshi/app/settings/update/VersionIo.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'package:html/dom.dart' as dom;
import 'package:package_info_plus/package_info_plus.dart';
import 'package:html/parser.dart' as parser;


/// 版本更新 组件
/// 配置：
///      VersionConfig.apply {
///             getNewVersionUrl = ""
///             apkDownloadUrl = ""
///             limitMin = 1
///      }
/// action中 调用实例 ：
///      Version.tryUpdate(this); || Version.tryUpdate(this,false);  //更新尝试支持忽略版本|更新尝试不支持忽略版本
///      启动后台任务定时任务  Version.bgCheck(this);
///
class Version extends VersionIo {
  late String _versionValue;
  late String _appVersionName;
  late SharedPreferences _prefs;

  Version(BuildContext context) {
    this.context = context;
    _initSharedPreferences();
  }

  Future<void> _initSharedPreferences() async {
    _prefs = await SharedPreferences.getInstance();
  }

  Future<String> ignoreVersion([String version = ""]) async {
    const key = "ignoreVersion";
    if (version.isNotEmpty) {
      await _prefs.setString(key, version);
      return version;
    } else {
      return _prefs.getString(key) ?? "1.0.0";
    }
  }

  Future<String> checkNew() async {
    final String url = VersionConfig.getNewVersionUrl;
    if (url.isEmpty) return "";

    try {
      final http.Response response = await curl(url);
      if (response.statusCode != 200) return "";

      final String responseBody = response.body;
      if (responseBody.startsWith("{")) {
        final Map<String, dynamic> jsonData = json.decode(responseBody);
        if (jsonData.containsKey("url")) {
          VersionConfig.apkDownloadUrl = jsonData["url"].toString();
        }
        return jsonData["version"].toString();
      }

      if (responseBody.startsWith("<") && url.contains("releases")) {
        final List<dom.Element> aElements = _parseReleasesHtml(responseBody, url);
        if (aElements.isNotEmpty) {
          final dom.Element firstAEle = aElements.first;
          final String href = firstAEle.attributes["href"] ?? "";
          if (href.isEmpty) return "";

          final RegExp reg = RegExp(r".+\/releases\/download\/(.+)\/.+");
          final RegExpMatch? match = reg.firstMatch(href);
          final String version = match?.group(1) ?? "";

          final Uri baseUri = Uri.parse(url);
          VersionConfig.apkDownloadUrl = "${baseUri.scheme}://${baseUri.host}$href";

          return version;
        }
      }
    } catch (e) {
      debugPrint("检查版本失败：$e");
    }
    return "";
  }

  List<dom.Element> _parseReleasesHtml(String html, String url) {
    final dom.Document doc = parser.parse(html);
    if (url.contains("github.com")) {
      return doc.querySelectorAll("a.Truncate");
    } else if (url.contains("gitee.com")) {
      return doc.querySelectorAll(".releases-download-list .item a")
          .where((ele) => ele.className.isEmpty)
          .toList();
    }
    return [];
  }

  Future<String> getMyVersionName() async {
    try {
      final PackageInfo packageInfo = await PackageInfo.fromPlatform();
      _appVersionName = packageInfo.version;
      return _appVersionName;
    } catch (e) {
      debugPrint("获取当前版本失败：$e");
      return "";
    }
  }

  Future<void> upRun() async {
    if (VersionConfig.apkDownloadUrl.isEmpty) {
      _showToast("APK 下载链接为空");
      return;
    }

    final String apkFileName = "${context.packageName}.$_versionValue.apk";
    final File? existingApk = await _getExistingApkFile(apkFileName);
    if (existingApk != null && existingApk.existsSync()) {
      await installApk(existingApk);
      return;
    }

    _showToast("新包后台下载中，下载完成后将启动安装");
    final File? downloadedApk = await downloadFile(
      VersionConfig.apkDownloadUrl,
      apkFileName,
    );

    if (downloadedApk != null && downloadedApk.existsSync()) {
      await installApk(downloadedApk);
    } else {
      _showToast("APK 下载失败，请稍后重试");
    }
  }

  Future<File?> _getExistingApkFile(String fileName) async {
    try {
      final Directory? externalDir = await getExternalStorageDirectory();
      if (externalDir == null) return null;
      final File file = File("${externalDir.path}/$fileName");
      return file.existsSync() ? file : null;
    } catch (e) {
      debugPrint("获取已存在 APK 失败：$e");
      return null;
    }
  }

  Future<bool> haveNew({bool canIgnore = true}) async {
    _appVersionName = await getMyVersionName();
    _versionValue = await checkNew();
    if (_appVersionName.isEmpty || _versionValue.isEmpty) {
      return false;
    }

    if (canIgnore) {
      final String ignoredVersion = await ignoreVersion();
      if (ignoredVersion == _versionValue) {
        return false;
      }
    }

    return _compareVersion(_appVersionName, _versionValue) < 0;
  }

  int _compareVersion(String v1, String v2) {
    final List<int> v1Parts = v1.split(".").map(int.parse).toList();
    final List<int> v2Parts = v2.split(".").map(int.parse).toList();
    final int maxLength = v1Parts.length > v2Parts.length ? v1Parts.length : v2Parts.length;

    for (int i = 0; i < maxLength; i++) {
      final int v1Part = i < v1Parts.length ? v1Parts[i] : 0;
      final int v2Part = i < v2Parts.length ? v2Parts[i] : 0;
      if (v1Part > v2Part) return 1;
      if (v1Part < v2Part) return -1;
    }
    return 0;
  }

  Future<void> confirmShow() async {
    if (_versionValue.isEmpty) return;

    await showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext dialogContext) {
        return AlertDialog(
          title: const Text("发现新版本"),
          content: Text("检测到新版本 $_versionValue，是否进行升级？"),
          actions: [
            TextButton(
              onPressed: () async {
                await ignoreVersion(_versionValue);
                Navigator.pop(dialogContext);
              },
              child: const Text("忽略这个版本", style: TextStyle(color: Colors.grey)),
            ),
            TextButton(
              onPressed: () async {
                Navigator.pop(dialogContext);
                await upRun();
              },
              child: const Text("确定"),
            ),
          ],
        );
      },
    );
  }

  void _showToast(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), duration: const Duration(seconds: 2)),
    );
  }

  static Future<void> bgRun(Future<void> Function() block) async {
    try {
      await block();
    } catch (e) {
      debugPrint("后台任务执行失败：$e");
    }
  }

  static void mainRun(VoidCallback block) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      block();
    });
  }

  static Future<void> bgCheck(BuildContext context) async {

      var v = Version(context);
      var interval = VersionConfig.limitMin*60*1000;
      while(true){
        await Future.delayed(Duration(microseconds: interval));
        debugPrint("更新检查中...");
        if(await v.haveNew()) {
          v.confirmShow();
        }
      }
  }

  static Future<void> tryUpdate(BuildContext context, [bool canIgnore = true]) async {
    try {
      final Version version = Version(context);
      await version._initSharedPreferences();
      if (await version.haveNew(canIgnore: canIgnore)) {
        mainRun(() => version.confirmShow());
      } else if (!canIgnore) {
        version._showToast("当前已是最新版本");
      }
    } catch (e) {
      debugPrint("尝试更新失败：$e");
    }
  }
}

extension on BuildContext {
  get packageName {
    return "edic";
    // // 1. 获取 PackageInfo 实例（包含应用所有配置信息）
    // PackageInfo packageInfo = await PackageInfo.fromPlatform();
    // return packageInfo.packageName;
  }
}
    